/**
* Project RFIDstation - test RFID Mifare shield
* Version 0.1
*
* Toolchain:   Arduino 1.5.8
* Device:      Arduino Leonardo
* Libraries:   Adafruit-Thermal-Printer-Library (https://github.com/adafruit/Adafruit-Thermal-Printer-Library)
*              RfidMifareShield
*
* 10/25/14 (v0.1) original version
*/

/* Includes */
#include "rfid.h"

/* Shared variables */
const int tagPin = 5;

/**
* @brief  Initialization of serial ports (PC/RFID) and LEDs
*/
void setup() {
  const int PC_BAUDRATE = 9600;
  const int RFID_BAUDRATE = 9600;

  // Configure CDC USB for PC interface
  Serial.begin(PC_BAUDRATE);

  // Configure USART0 and pin for RFID Mifare shield
  Serial1.begin(RFID_BAUDRATE);
  pinMode(tagPin, INPUT);
}


/**
* @brief  Check tag present, read tag value, then send value to PC
*/
void loop() {
  static boolean tagPresent = false;

  // check for tag presence
  if ((digitalRead(tagPin) == LOW) && (tagPresent == false)) {
    tagPresent = true;
    Serial.print("Tag present at ");
    Serial.println(millis());
    // Read
    testRfidMifareShield();
  } else {
    // Check for tag disappearance
    if ((digitalRead(tagPin) == HIGH) && (tagPresent == true)) {
      tagPresent = false;
      Serial.print("Tag disappear at ");
      Serial.println(millis());
    } else {
    }
  }
  delay(100);
}


/**
* @brief  Send command packet to RFID Mifare shield 
* @arg    command  command packet
* @retval None 
*/
void sendRfidCommand(unsigned char command[]) {
  int i;
  unsigned int len;
  unsigned char checksum = 0;

  len = command[1];
  for (i = 0; i < (len + 1); i++) {
    checksum =  checksum ^ command[i];
  }

  for (i = 0; i < (len + 1); i++) {
    Serial1.write(command[i]);
  }
  Serial1.write(checksum);
}


/* Receive response packet from RFID Mifare shield */
unsigned int receiveRfidResponse(unsigned char buf[]) {
  unsigned int i = 0;
  unsigned int cnt = 0;
  unsigned int len = 0;
  byte inByte;
  
  while (1) {
    delay(1);
    if (++i >= 50) {
      return 0;
    }
    if (Serial1.available() > 0) {
      inByte = Serial1.read();
      if (inByte == 0xBD) {
        break;
      } else {
        return 0;
      }
    }
  }
  i = 0;
  while (1) {
    delay(1);
    if (++i >= 50) {
      return 0;
    }
    if (Serial1.available() > 0) {
      inByte = Serial1.read();
      buf[0] = inByte;
      break;
    }
  }
  for (cnt = 1; cnt < (buf[0] + 1); cnt++) {
    i = 0;
    while (1) {
      delay(1);
      if (i++ >= 50) {
        return 0;
      }
      if (Serial1.available() > 0)
      {
        i = 0;
        inByte = Serial1.read();
        buf[cnt] = inByte;
        break;
      }
      if (cnt >= buf[0] )
        return (buf[0]);
    }
  }
}


/* Test RFID Mifare shield */
void testRfidMifareShield() {
  int len = 0;
  int j = 0;
  unsigned char cardType;
  char errCode;
  unsigned char cmd[26];
  unsigned char buf[26];

  delay(10);
  // Format command packet [SELECT CARD], send and receive response packet
  memcpy(cmd, SelectCard, sizeof(SelectCard));
  sendRfidCommand(cmd);
  len = receiveRfidResponse(buf);
  if (len < 1)
    return;
  if ((buf[1] != 1) || (buf[2] != 0)) {
    return;
  }
  if (buf[0] == 8) {
    cardType = buf[7];
  } else {
    cardType = buf[10];
  }
  
  // Report tag type
  switch (cardType) {
    case 1: //Mifare Std 1K
      Serial.print("Mifare Std 1K");
      errCode = 0;
      break;
    case 2: //Mifare_Pro
      Serial.print("Mifare Pro");
      errCode = -1;
      break;
    case 3: //Mifare UltraLight
      Serial.print("Mifare Ultralight");
      errCode = 0;
      break;
    case 4: //Mifare Std 4K
      Serial.print("Mifare Std 4K");
      errCode = 0;
      break;
    case 5: //Mifare_ProX
      Serial.print("Mifare Pro X");
      errCode = -1;
      break;
    case 6: //Mifare_DesFire
      Serial.print("Mifare Desfire");
      errCode = -1;
      break;
    case 7: //Mifare_mini_320Byte
      Serial.print("Mifare Mini 320b");
      errCode = 0;
      break;
    default:
      errCode = 1;
      break;
  }
  
  // Report error code
  if (errCode == 0) {
    Serial.println(": Success");
  } else {
    Serial.println(": Error");
  }
}

